const vs = `
  attribute vec3 aPos;
  attribute vec2 aVertexTextureCoord;
  varying highp vec2 vTextureCoord;

  void main(void){
    gl_Position = vec4(aPos, 1);
    vTextureCoord = aVertexTextureCoord;
  }
`;

const fs = `
  varying highp vec2 vTextureCoord;
  uniform sampler2D uSampler;

  void main(void) {
    gl_FragColor = texture2D(uSampler, vTextureCoord);
  }
`;

const vertex = [
  -1, -1, 0.0,
  1, -1, 0.0,
  1, 1, 0.0,
  -1, 1, 0.0,
];

const vertexIndice = [
  0, 1, 2,
  0, 2, 3,
];

const texCoords = [
  0.0, 0.0,
  1.0, 0.0,
  1.0, 1.0,
  0.0, 1.0,
];
function createShader(gl, src, type) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, src);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    console.error(`Error compiling shader: ${gl.getShaderInfoLog(shader)}`);
  }
  return shader;
}

const buffers = {};

function createRenderer(canvas, width, height) {
  const gl = canvas.getContext('webgl');
  if (!gl) {
    console.error('Unable to get webgl context.');
    return;
  }

  const info = xhs?.getSystemInfoSync();
  gl.canvas.width = info.pixelRatio * width;
  gl.canvas.height = info.pixelRatio * height;
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);

  const vertexShader = createShader(gl, vs, gl.VERTEX_SHADER);
  const fragmentShader = createShader(gl, fs, gl.FRAGMENT_SHADER);

  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.error('Unable to initialize the shader program.');
    return;
  }

  gl.useProgram(program);

  const texture = gl.createTexture();
  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.bindTexture(gl.TEXTURE_2D, null);

  buffers.vertexBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffers.vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex), gl.STATIC_DRAW);

  buffers.vertexIndiceBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.vertexIndiceBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(vertexIndice), gl.STATIC_DRAW);

  const aVertexPosition = gl.getAttribLocation(program, 'aPos');
  gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(aVertexPosition);

  buffers.trianglesTexCoordBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffers.trianglesTexCoordBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoords), gl.STATIC_DRAW);

  const vertexTexCoordAttribute = gl.getAttribLocation(program, 'aVertexTextureCoord');
  gl.enableVertexAttribArray(vertexTexCoordAttribute);
  gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0);

  const samplerUniform = gl.getUniformLocation(program, 'uSampler');
  gl.uniform1i(samplerUniform, 0);

  return (arrayBuffer, width, height) => {
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBuffer);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
  };
}

Page({
  onShareAppMessage() {
    return {
      title: 'camera',
      path: 'page/component/pages/camera/camera',
    };
  },

  data: {
    src: '',
    videoSrc: '',
    position: 'back',
    mode: 'scanCode',
    result: {},
    frameWidth: 0,
    frameHeight: 0,
    width: 288,
    height: 358,
    showCanvas: false,
  },

  onReady() {
    this.ctx = xhs?.createCameraContext();
    // const selector = xhs?.createSelectorQuery();
    // selector.select('#webgl')
    // .node(this.init)
    // .exec()
  },
  init(res) {
    if (this.listener) {
      this.listener.stop();
    }
    const canvas = res.node;
    const render = createRenderer(canvas, this.data.width, this.data.height);

    // if (!render || typeof render !== 'function') return

    this.listener = this.ctx.onCameraFrame(frame => {
      render(new Uint8Array(frame.data), frame.width, frame.height);

      const {
        frameWidth,
        frameHeight,
      } = this.data;

      if (frameWidth === frame.width && frameHeight == frame.height) return;
      this.setData({
        frameWidth: frame.width,
        frameHeight: frame.height,

      });
    });
    this.listener.start();
  },
  takePhoto() {
    this.ctx.takePhoto({
      quality: 'high',
      success: res => {
        this.setData({
          src: res.tempImagePath,
        });
      },
    });
  },
  startRecord() {
    this.ctx.startRecord({
      success: () => {
        console.log('startRecord');
      },
    });
  },
  stopRecord() {
    this.ctx.stopRecord({
      success: res => {
        this.setData({
          src: res.tempThumbPath,
          videoSrc: res.tempVideoPath,
        });
      },
    });
  },
  togglePosition() {
    this.setData({
      position: this.data.position === 'front'
        ? 'back' : 'front',
    });
  },
  error(e) {
    console.log(e.detail);
  },

  handleShowCanvas() {
    const that = this;

    this.setData({
      showCanvas: !this.data.showCanvas,
    }, () => {
      if (this.data.showCanvas) {
        const selector = xhs?.createSelectorQuery();
        selector.select('#webgl')
          .node(this.init)
          .exec();
      }
    });
  },
});
